package com.three.digit.tools;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;

import org.apache.commons.lang.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;

import com.three.digit.model.Point;

public class Utils
{
    public static void writeMapToExcel (String file, Map <Integer, Integer> map) throws Exception
    {
        HSSFWorkbook wb = new HSSFWorkbook ();
        HSSFSheet sheet = wb.createSheet ();

        Set <Integer> keySet = map.keySet ();

        int rowIndex = 0;
        for (Integer integer : keySet)
        {
            HSSFRow row = sheet.createRow (rowIndex++);
            HSSFCell cell = row.createCell (0);
            cell.setCellValue (map.get (integer));

            cell = row.createCell (1);
            cell.setCellValue (integer);
        }

        FileOutputStream fileOut = new FileOutputStream (file);

        wb.write (fileOut);
        fileOut.close ();
    }

    @SuppressWarnings ("deprecation")
    public static void writeMapToExcel (String file, List <String[]> data) throws Exception
    {
        HSSFWorkbook wb = new HSSFWorkbook ();
        HSSFSheet sheet = wb.createSheet ();

        for (int i = 0; i < data.size (); i++)
        {
            HSSFRow row = sheet.createRow (i);

            String[] rowData = data.get (i);
            for (int j = 0; j < rowData.length; j++)
            {
                HSSFCell cell = row.createCell (j);
                cell.setCellValue (rowData[j]);
            }
        }

        FileOutputStream fileOut = new FileOutputStream (file);

        wb.write (fileOut);
        fileOut.close ();
    }

    public static List <Point> readPoints (String path)
    {
        List <Point> points = new ArrayList <Point> ();

        BufferedReader br = null;
        try
        {
            br = new BufferedReader (new InputStreamReader (ClassLoader.getSystemResourceAsStream (path)));

            String temp;
            while ((temp = br.readLine ()) != null)
            {
                StringTokenizer stringTokenizer = new StringTokenizer (temp, " ");
                List <String> l = new ArrayList <String> ();

                while (stringTokenizer.hasMoreElements ())
                {
                    l.add ((String) stringTokenizer.nextElement ());
                }

                points.add (new Point (l.get (0), l.get (1), l.get (2), l.get (3)));
            }
        }
        catch (Exception e)
        {
            e.printStackTrace ();
        }
        finally
        {
            if (br != null)
            {
                try
                {
                    br.close ();
                }
                catch (IOException e)
                {
                    e.printStackTrace ();
                }
            }
        }
        return points;
    }
    
    public static Point readPoint (String path)
    {
        Point root = null;

        BufferedReader br = null;
        try
        {
            br = new BufferedReader (new InputStreamReader (ClassLoader.getSystemResourceAsStream (path)));

            String temp;
            Point cursor = null;
            Point previous = null;
            while ((temp = br.readLine ()) != null)
            {
                StringTokenizer stringTokenizer = new StringTokenizer (temp, " ");
                List <String> l = new ArrayList <String> ();

                while (stringTokenizer.hasMoreElements ())
                {
                    l.add ((String) stringTokenizer.nextElement ());
                }

                cursor = new Point (l.get (0), l.get (1), l.get (2), l.get (3));
                
                if (root == null) {
					root = cursor;
				}else{
					previous.setNext(cursor);
	                cursor.setPrevious(previous);
				}
                previous = cursor;
            }
        }
        catch (Exception e)
        {
            e.printStackTrace ();
        }
        finally
        {
            if (br != null)
            {
                try
                {
                    br.close ();
                }
                catch (IOException e)
                {
                    e.printStackTrace ();
                }
            }
        }
        return root;
    }

    public static HashMap <Integer, Point> toHashMap (List <Point> ps)
    {
        HashMap <Integer, Point> hm = new HashMap <Integer, Point> ();
        for (Point point : ps)
        {
            hm.put (point.getId (), point);
        }
        return hm;
    }

    public static Point next (Point point, List <Point> ps)
    {
        for (int i = 0; i < ps.size (); i++)
        {
            Point index = ps.get (i);

            if (index.getId () == point.getId () && (i + 1) < ps.size ())
            {
                return ps.get (i + 1);
            }
        }
        return null;
    }

    public static Point previous (Point point, List <Point> ps)
    {
        for (int i = 0; i < ps.size (); i++)
        {
            Point index = ps.get (i);

            if (index.getId () == point.getId () && (i - 1) >= 0)
            {
                return ps.get (i - 1);
            }
        }
        return null;
    }

    public static List <Point> generateAllPoints ()
    {
        List <Point> points = new ArrayList <Point> ();
        for (int i = 0; i < 1000; i++)
        {
            points.add (new Point (i, i));
        }
        return points;
    }

    public static Point randomPoint ()
    {
        return new Point (0, (int) (Math.random () * 1000));
    }

    public static List <Point> randomPoints (int count)
    {
        List <Point> points = new ArrayList <Point> ();
        for (int i = 0; i < count; i++)
        {
            points.add (randomPoint ());
        }
        return points;
    }

    public static void writeToFile (List <Point> points, String filePath)
    {
        BufferedWriter out = null;
        try
        {
            out = new BufferedWriter (new FileWriter (filePath));

            for (Point p : points)
            {
                out.write (p.toString ());
                out.newLine ();
            }
        }
        catch (Exception e)
        {
            e.printStackTrace ();
        }
        finally
        {
            try
            {
                out.close ();
            }
            catch (IOException e)
            {
            }
        }
        System.out.println ("---------success---------");
    }

    public static void avgList (List <Integer> list)
    {
        int sum = 0;
        for (int i = 0; i < list.size (); i++)
        {
            sum += list.get (i);
        }
        System.out.println (Double.valueOf (sum + "") / Double.valueOf (list.size () + ""));
    }

    public static void print (List <Point> points)
    {
        System.out.println ("The number of size is: " + points.size ());
        String header = String.format (Point.FORMAT_STR, "id", "x", "y", "z");
        System.out.println (StringUtils.repeat (" ", 5) + header);
        System.out.println (StringUtils.repeat ("-", header.length () + 5));

        for (Point p : points)
        {
            System.out.println (p);
        }
    }
}
